package com.xinzhidi.web.controlset.service;

import com.aliyun.oss.ServiceException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinzhidi.common.constant.AgreementConstants;
import com.xinzhidi.common.core.domain.model.LoginUser;
import com.xinzhidi.common.core.page.TableDataInfo;
import com.xinzhidi.common.utils.DateUtils;
import com.xinzhidi.common.utils.SecurityUtils;
import com.xinzhidi.common.utils.StringUtils;
import com.xinzhidi.common.utils.ThreadPoolUtil;
import com.xinzhidi.common.utils.bean.BeanUtils;
import com.xinzhidi.web.build.domain.BuildUnit;
import com.xinzhidi.web.build.domain.CBuild;
import com.xinzhidi.web.build.service.IBuildUnitService;
import com.xinzhidi.web.build.service.ICBuildService;
import com.xinzhidi.web.controlset.domain.ControlSet;
import com.xinzhidi.web.controlset.domain.dto.ControlSetDto;
import com.xinzhidi.web.controlset.domain.dto.ControlSetListDto;
import com.xinzhidi.web.controlset.domain.po.ControlSetPo;
import com.xinzhidi.web.controlset.domain.vo.ControlSetListVo;
import com.xinzhidi.web.controlset.mapper.ControlSetMapper;
import com.xinzhidi.web.dataset.domain.dto.DataSetDto;
import com.xinzhidi.web.dataset.service.DataSetService;
import com.xinzhidi.web.equipment.domain.vo.EquipmentInfoVo;
import com.xinzhidi.web.equipment.service.EquipmentService;
import com.xinzhidi.web.house.domain.Household;
import com.xinzhidi.web.house.service.IHouseholdService;
import com.xinzhidi.web.plot.domain.entity.CPlot;
import com.xinzhidi.web.plot.service.ICPlotService;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


/**
 * 平衡调控数据设置Service业务层处理
 *
 * @author cx
 * @date 2023-06-27
 */
@Service
public class ControlSetService extends ServiceImpl<ControlSetMapper, ControlSet> {

    @Autowired
    private ControlSetMapper setMapper;

    @Autowired
    private DataSetService dataSetService;

    @Autowired
    private ThreadPoolUtil threadPoolUtil;

    @Autowired
    private EquipmentService equipmentService;

    @Autowired
    private ICPlotService plotService;

    @Autowired
    private ICBuildService buildService;

    @Autowired
    private IBuildUnitService buildUnitService;

    @Autowired
    private IHouseholdService householdService;
    ;

    /**
     * 查询平衡调控数据设置列表
     *
     * @param dto 查询平衡调控数据设置dto
     * @return 平衡调控数据设置
     */
    public TableDataInfo<ControlSetListVo> selectDataSetList(ControlSetListDto dto) {
        LambdaQueryWrapper<ControlSet> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(StringUtils.isNotBlank(dto.getType()), ControlSet::getType, dto.getType());
        wrapper.eq(dto.getPlotId() != null, ControlSet::getPlotId, dto.getPlotId());
        wrapper.eq(dto.getBuildId() != null, ControlSet::getBuildId, dto.getBuildId());
        wrapper.eq(dto.getUnitId() != null, ControlSet::getUnitId, dto.getUnitId());
        wrapper.eq(dto.getHouseholdId() != null, ControlSet::getHouseholdId, dto.getHouseholdId());
        wrapper.orderByDesc(ControlSet::getId);
        List<ControlSet> list = setMapper.selectList(wrapper);
        List<ControlSetListVo> listVos = Lists.newArrayList();
        if (CollectionUtils.isEmpty(list)) {
            return TableDataInfo.getDataTable(listVos);
        }
        return TableDataInfo.getDataTable(setMapper.selectList(wrapper), (domain -> {
            ControlSetListVo vo = new ControlSetListVo();
            BeanUtils.copyProperties(domain, vo);
            return vo;
        }));
    }

    public ControlSetListVo getControlSetInfo(ControlSetPo po) {
        ControlSetListVo vo = null;
        ControlSetListDto dto = new ControlSetListDto();
        BeanUtils.copyProperties(po, dto);
        TableDataInfo<ControlSetListVo> tableDataInfo = selectDataSetList(dto);
        if (tableDataInfo.getTotal() > 0) {
            vo = tableDataInfo.getRows().get(0);
        }
        return vo;
    }

    public Integer insertControlSet(ControlSetDto dto) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        ControlSet controlSet = new ControlSet();
        BeanUtils.copyProperties(dto, controlSet);
        Integer num;
        if (dto.getId() == null) {
            LambdaQueryWrapper<ControlSet> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(ControlSet::getType, dto.getType())
                    .eq(dto.getPlotId() != null, ControlSet::getPlotId, dto.getPlotId())
                    .eq(dto.getBuildId() != null, ControlSet::getBuildId, dto.getBuildId())
                    .eq(dto.getUnitId() != null, ControlSet::getUnitId, dto.getUnitId())
                    .eq(dto.getHouseholdId() != null, ControlSet::getHouseholdId, dto.getHouseholdId());
            ControlSet selectOne = setMapper.selectOne(queryWrapper);
            if (selectOne != null) {
                throw new ServiceException("设置已存在");
            }
            controlSet.setCreateBy(loginUser.getUserId().toString());
            controlSet.setCreateTime(DateUtils.getNowDate());
            num = setMapper.insert(controlSet);

        } else {
            controlSet.setUpdateBy(loginUser.getUserId().toString());
            controlSet.setUpdateTime(DateUtils.getNowDate());
            num = setMapper.updateById(controlSet);
        }
        DataSetDto dataSetDto = new DataSetDto();
        BeanUtils.copyProperties(dto, dataSetDto);
        dataSetDto.setSource(1);
        dataSetService.sendMessage("2", dataSetDto, AgreementConstants.InstructBusinessType.MANUAL_METER_READ);

        dataSetService.updateRelevanceData("2", dto.getType(), dto.getPlotId(), dto.getBuildId(), dto.getUnitId(), dto.getHouseholdId(), dto.getRegulationMethod(), dto.getControlStrategy(), dto.getPriority());
        return num;
    }

    /**
     * 修改相关初始设置  如设置了某个小区，则同时设置小区下的楼栋、单元、住户表的调控方法及调控策略
     *
     * @param setType 设置类型（1：初始设置  2：平衡调控）  备注：初始设置是包含关系。平衡调控只会调控本维度，不包含下级
     * @return 成功返回true 失败返回false
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean batchControlSet(List<ControlSetDto> dtoList, String setType) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        List<ControlSet> controlSetList = Lists.newArrayList();
        for (ControlSetDto dto : dtoList) {
            ThreadPoolExecutor threadPool = threadPoolUtil.getThreadPoolByDefault();
            threadPool.execute(() -> {
                String type = dto.getType();
                LambdaQueryWrapper<ControlSet> wrapper = Wrappers.lambdaQuery();
                wrapper.eq(ControlSet::getType, type);
                if (type.equals(AgreementConstants.DataType.PLOT)) {
                    wrapper.eq(ControlSet::getPlotId, dto.getPlotId());
                } else if (type.equals(AgreementConstants.DataType.BUILD)) {
                    wrapper.eq(ControlSet::getBuildId, dto.getBuildId());
                } else if (type.equals(AgreementConstants.DataType.BUILD_UNIT)) {
                    wrapper.eq(ControlSet::getUnitId, dto.getUnitId());
                } else if (type.equals(AgreementConstants.DataType.HOUSEHOLD)) {
                    wrapper.eq(ControlSet::getHouseholdId, dto.getHouseholdId());
                }
                ControlSet controlSet = new ControlSet();
                List<ControlSet> setList = setMapper.selectList(wrapper);
                if (CollectionUtils.isNotEmpty(setList)) {
                    //按照创建时倒序排序
                    setList = setList.stream().sorted(Comparator.comparing(ControlSet::getCreateTime).reversed()).collect(Collectors.toList());
                    controlSet = setList.get(0);
                }
                Long id = null;
                if (controlSet != null) {
                    id = controlSet.getId();
                    controlSet.setUpdateBy(loginUser.getUserId().toString());
                    controlSet.setUpdateTime(DateUtils.getNowDate());
                } else {
                    controlSet = new ControlSet();
                    BeanUtils.copyProperties(dto, controlSet);
                    controlSet.setCreateBy(loginUser.getUserId().toString());
                    controlSet.setCreateTime(DateUtils.getNowDate());
                }
                BeanUtils.copyProperties(dto, controlSet);
                controlSet.setId(id);
                controlSet.setCreateBy(loginUser.getUserId().toString());
                controlSet.setCreateTime(DateUtils.getNowDate());
                controlSetList.add(controlSet);
                this.saveOrUpdate(controlSet);

                DataSetDto dataSetDto = new DataSetDto();
                BeanUtils.copyProperties(dto, dataSetDto);
                dataSetService.sendMessage(setType, dataSetDto, AgreementConstants.InstructBusinessType.MANUAL_METER_READ);
                dataSetService.updateRelevanceData(setType, dto.getType(), dto.getPlotId(), dto.getBuildId(), dto.getUnitId(), dto.getHouseholdId(), dto.getRegulationMethod(), dto.getControlStrategy(), dto.getPriority());
            });
        }
        return true;
    }

    public boolean oneKeyRegulation(ControlSetPo po) {
        String type = po.getType();
        ControlSetDto dto;
        List<ControlSetDto> dtoList = Lists.newArrayList();
        List<EquipmentInfoVo> equipmentList;
//        List<Long> ids = Lists.newArrayList();
        if (type.equals(AgreementConstants.DataType.PLOT)) {
            List<CPlot> plotList = plotService.list(new LambdaQueryWrapper<>(CPlot.class)
                    .eq(po.getPlotId() != null, CPlot::getId, po.getPlotId()));
            if (CollectionUtils.isNotEmpty(plotList)) {
                for (CPlot plot : plotList) {
                    dto = new ControlSetDto();
                    dto.setType(type);
                    dto.setPlotId(plot.getId());
                    dto.setBuildingValveOpen(po.getBuildingValveOpen());
                    dto.setUnitValveOpen(po.getUnitValveOpen());
                    dto.setHouseholdValveOpen(po.getHouseholdValveOpen());
                    dtoList.add(dto);
                }
            }
        } else if (type.equals(AgreementConstants.DataType.BUILD)) {
            List<CBuild> buildList = buildService.list(new LambdaQueryWrapper<>(CBuild.class)
                    .eq(po.getPlotId() != null, CBuild::getPlotId, po.getPlotId())
                    .eq(po.getBuildId() != null, CBuild::getId, po.getBuildId()));
            if (CollectionUtils.isNotEmpty(buildList)) {
                for (CBuild build : buildList) {
                    dto = new ControlSetDto();
                    dto.setType(type);
                    dto.setPlotId(build.getPlotId());
                    dto.setBuildId(build.getId());
                    dto.setBuildingValveOpen(po.getBuildingValveOpen());
                    dto.setUnitValveOpen(po.getUnitValveOpen());
                    dto.setHouseholdValveOpen(po.getHouseholdValveOpen());
                    dtoList.add(dto);
                }
            }
        } else if (type.equals(AgreementConstants.DataType.BUILD_UNIT)) {
            List<BuildUnit> buildUnitList = buildUnitService.list(new LambdaQueryWrapper<>(BuildUnit.class)
                    .eq(po.getPlotId() != null, BuildUnit::getLotId, po.getPlotId())
                    .eq(po.getBuildId() != null, BuildUnit::getBuildId, po.getBuildId())
                    .eq(po.getUnitId() != null, BuildUnit::getId, po.getUnitId()));
            if (CollectionUtils.isNotEmpty(buildUnitList)) {
                for (BuildUnit buildUnit : buildUnitList) {
                    dto = new ControlSetDto();
                    dto.setType(type);
                    dto.setPlotId(buildUnit.getLotId());
                    dto.setBuildId(buildUnit.getBuildId());
                    dto.setUnitId(buildUnit.getId());
                    dto.setUnitValveOpen(po.getUnitValveOpen());
                    dto.setHouseholdValveOpen(po.getHouseholdValveOpen());
                    dtoList.add(dto);
                }
            }
        } else if (type.equals(AgreementConstants.DataType.HOUSEHOLD)) {
            List<Household> householdList = householdService.list(new LambdaQueryWrapper<>(Household.class)
                    .eq(po.getPlotId() != null, Household::getPlotId, po.getPlotId())
                    .eq(po.getBuildId() != null, Household::getBuildId, po.getBuildId())
                    .eq(po.getUnitId() != null, Household::getUnit, po.getUnitId())
                    .eq(StringUtils.isNotBlank(po.getHouseHoldType()), Household::getType, po.getHouseHoldType()));
            if (CollectionUtils.isNotEmpty(householdList)) {
                for (Household household : householdList) {
                    dto = new ControlSetDto();
                    dto.setType(type);
                    dto.setPlotId(household.getPlotId());
                    dto.setBuildId(household.getBuildId());
                    dto.setUnitId(household.getUnit());
                    dto.setHouseholdId(household.getId());
                    dto.setHouseholdValveOpen(po.getHouseholdValveOpen());
                    dtoList.add(dto);
                }
            }
        }

        dtoList.stream().forEach(setDto -> setDto.setRegulationMethod(po.getRegulationMethod()));
        if (po.getPriority() != null) {
            dtoList.stream().forEach(setDto -> setDto.setPriority(po.getPriority()));
        }

        return this.batchControlSet(dtoList, "1");


//        String type = po.getType();
//        ControlSetDto dto;
//        List<ControlSetDto> dtoList = Lists.newArrayList();
//        List<EquipmentInfoVo> equipmentList;
//        List<Long> ids = Lists.newArrayList();
//        if (type.equals(AgreementConstants.DataType.PLOT)) {
//            ids = plotService.list(new LambdaQueryWrapper<>(CPlot.class)
//                            .eq(po.getPlotId() != null , CPlot::getId , po.getPlotId()))
//                    .stream().map(CPlot::getId).collect(Collectors.toList());
//        } else if (type.equals(AgreementConstants.DataType.BUILD)) {
//            ids = buildService.list(new LambdaQueryWrapper<>(CBuild.class)
//                    .eq(po.getBuildId() != null, CBuild::getId , po.getBuildId()))
//                    .stream().map(CBuild::getId).collect(Collectors.toList());
//
//        } else if (type.equals(AgreementConstants.DataType.BUILD_UNIT)) {
//            ids = buildUnitService.list(new LambdaQueryWrapper<>(BuildUnit.class)
//                    .eq(po.getUnitId() != null, BuildUnit::getId , po.getUnitId()))
//                    .stream().map(BuildUnit::getId).collect(Collectors.toList());
//        } else if (type.equals(AgreementConstants.DataType.HOUSEHOLD)) {
//            ids = householdService.list(new LambdaQueryWrapper<>(Household.class)
//                            .eq(StringUtils.isNotBlank(po.getHouseHoldType()), Household::getType , po.getHouseHoldType())
//                    .eq(po.getHouseholdId() != null, Household::getId , po.getHouseholdId()))
//                    .stream().map(Household::getId).collect(Collectors.toList());
//        }
//
//        equipmentList = equipmentService.getEquipmentListByDim("1" , type , ids);
//        if(CollectionUtils.isEmpty(equipmentList)){
//            throw new ServiceException("该维度下没有设备!");
//        }
//        //排除掉海马阀门表
//        equipmentList = equipmentList.stream().filter(equipmentInfoVo -> equipmentInfoVo.getProtocolType() != AgreementConstants.AgreementType.SEAHORSE_VALVE_METER).collect(Collectors.toList());
//        if(CollectionUtils.isEmpty(equipmentList)){
//            throw new ServiceException("该维度下没有设备!");
//        }
//        for (EquipmentInfoVo equipmentInfoVo : equipmentList) {
//            dto = new ControlSetDto();
//            dto.setType(type);
//            dto.setPlotId(equipmentInfoVo.getLotId());
//
//            if(equipmentInfoVo.getBuildId() != null){
//                dto.setBuildId(equipmentInfoVo.getBuildId());
//                dto.setBuildingValveOpen(po.getBuildingValveOpen());
//            }
//            if(equipmentInfoVo.getUnitId() != null){
//                dto.setUnitId(equipmentInfoVo.getUnitId());
//                dto.setUnitValveOpen(po.getUnitValveOpen());
//            }
//            if(equipmentInfoVo.getHouseholdId() != null){
//                dto.setHouseholdId(equipmentInfoVo.getHouseholdId());
//                dto.setHouseholdValveOpen(po.getHouseholdValveOpen());
//            }
//            dtoList.add(dto);
//        }
//
//        return this.batchControlSet(dtoList , "1");
    }
}
